package com.excel.util;

import com.excel.mapper.PubImpExcelJdLogMapper;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.stream.Collectors;

@Component
public class ExcelImportUtil {

    @Resource
    private SqlSessionFactory sqlSessionFactory;

    public List<String> selectByStringFieldInList(String tableName, String field, List<String> Fields, Boolean checkDelete) {

        List<String> resultList = batchSelect(Fields, PubImpExcelJdLogMapper.class,(mapper, fieldList) -> {
            List<String> result = new ArrayList<>();
            switch (tableName){
                case "mb_org_employee_info":
                    result = mapper.selectStringFieldInListEmploy( field, fieldList, checkDelete);
                    return result;
                case "mb_org_info":
                    result = mapper.selectStringFieldInListOrg( field, fieldList, checkDelete);
                    return result;
                case "mb_post_info":
                    result = mapper.selectStringFieldInListPost( field, fieldList, checkDelete);
                    return result;
            }
            return result;
        });

        return resultList;
    }


    public <T> List<T> selectByAllFieldInList(String tableName, String field, List<String> Fields,Boolean checkDelete) {

        List<T> resultList = batchSelect(Fields, PubImpExcelJdLogMapper.class,(mapper, fieldList) -> {

            List<T> result = new ArrayList<>();

            switch (tableName){
                case "mb_job":
                    result = (List<T>) mapper.selectAllFieldInListJob( field, fieldList, checkDelete);
                    return result;
            }

            return result;
        });

        return resultList;
    }


    public Map<String, Boolean> isExistByFieldInDb(String tableName, String field, List<String> Fields, Boolean checkDelete) {
        Map<String, Boolean> map = new HashMap<>(Fields.size());
        List<String> res = selectByStringFieldInList(tableName,field,Fields,checkDelete);
        map.putAll(Fields.stream().collect(Collectors.toMap(i -> i, t -> false,(k1, k2) -> k1)));
        map.putAll(res.stream().collect(Collectors.toMap(i -> i, t -> true,(k1, k2) -> k1)));
        return map;
    }

    public <K,V> Map<K, V> getALLFieldInDb(String tableName, String field, List<String> Fields, Boolean checkDelete, Function<V, K> fieldMapper) {

        List<V> res = selectByAllFieldInList(tableName, field, Fields, checkDelete);

        Map<K, V> map = new HashMap<>();
        for (V obj : res) {
            K key = fieldMapper.apply(obj);
            map.put(key, obj);
        }
        return map;
    }


    public <T, U, R> List<R> batchSelect(List<T> data, Class<U> mapperClass, BiFunction<U, List<T>, List<R>> queryFunction) {
        int i = 1;
        List<R> resultList = new ArrayList<>();
        SqlSession batchSqlSession = this.sqlSessionFactory.openSession(ExecutorType.BATCH);

        try {
            U mapper = batchSqlSession.getMapper(mapperClass);
            int size = data.size();
            List<T> idList = new ArrayList<>();

            for(Iterator var10 = data.iterator(); var10.hasNext(); ++i) {
                T element = (T) var10.next();
                idList.add(element);

                if (i % 100 == 0 || i == size) {
                    List<R> result = queryFunction.apply(mapper, idList);
                    resultList.addAll(result);
                    idList.clear();
                }
            }

            batchSqlSession.commit(!TransactionSynchronizationManager.isSynchronizationActive());
        } catch (Exception ex) {
            batchSqlSession.rollback();
            resultList.clear();
        } finally {
            batchSqlSession.close();
        }

        return resultList;
    }

}
